package event;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import event.collide.BorderCollisionEvent;
import event.collide.CollideRule;

import processing.core.PVector;

import run.Env;
import run.LineCell;

public class EventObserver {
	
	private LineCell c;
	
	// events triggered or observed by other cells that are being told to us
	private List<Event> externalEvents;
	
	private int idleTime = 0;
	
	public EventObserver(LineCell parent) {
		c = parent;
		externalEvents = new LinkedList<Event>();
	}
	
	public List<Event> poll() {
		List<Event> events = new ArrayList<Event>();
		PVector loc = c.loc;
		
		// TODO what about Events that are recorded by cell c
		// but really involve an other cell?
		// e.g. cell c explodes, other cells shall be notified...
		// give event to Env to put onto their queues (cross-cell communication)
		events.addAll(externalEvents);
		externalEvents.clear();
		
		// BorderCollisionEvent
	    int buf = 10;
		if (loc.x < buf || loc.y<buf || loc.x > (Env.xdim - buf) || loc.y > (Env.ydim - buf)) {
	    	events.add(new BorderCollisionEvent());
//	    	System.out.println("Border Collision");
	    }
		
	    // LineCollisionEvent
	    LineCell collided = Env.instance.isCollide(c);
	    if (collided != null) {
	    	events.add(new CellCollisionEvent(c, collided));
//	    	System.out.println("Cell Collision");
	    	
	    	// TODO notify collided cell
	    	Env.instance.send_message(collided, new IncomingCollisionEvent());
	    }
	    
	    
	    
	    
	    
	    // THIS actually doesn't fit the 'Event' model... it's an explicit function
	    // e.g. my stroke should be 5x+2 number of nearby cells
//	    List<LineCell> nearbyCells = Env.instance.getNearbyCells(c, 20);
//	    int num_nearbyCells = nearbyCells.size();
//	    events.add(new NearbyCellsEvent(num_nearbyCells));
//	    

	    List<LineCell> nearbyCells = Env.instance.getNearbyCells(c,30);
	    if (nearbyCells.size() > 0)
	    	events.add(new PaintTowardsNearbyCellsEvent(nearbyCells));
	    
	    if (c.getAge() > c.lifetime) {
	    	events.add(new CellExhaustedEvent());
	    }
	    
	    if (events.size() < 1)
	    	idleTime++;
	    
	    if (idleTime > 100) {
	    	events.add(new IdleEvent());
	    	idleTime = 0;
	    }
	    
		return events;
	}

	public void queueExternalEvent(Event e) {
		externalEvents.add(e);
	}

	/**
	 * Each instance of an EventObserver will have its own vector <0.5,.022,...?
	 * that characterizes its sensitivity to events. 
	 * This will be a random vector.
	 */
}
